package eiisan.config.mvc;

import com.google.common.escape.Escaper;
import com.google.common.html.HtmlEscapers;
import eiisan.config.mvc.async.AsyncConfig;
import eiisan.config.mvc.converter.JsonConverer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
import org.springframework.web.context.request.async.TimeoutCallableProcessingInterceptor;
import org.springframework.web.context.request.async.TimeoutDeferredResultProcessingInterceptor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * springMVC配置
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

	@Autowired
	private AsyncConfig asyncConfig;

	@Override
	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
		PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
		//设置页面传来的pageNum从1开始 --》 对应后台实际接受到位pageNum：0
		//即页面传来 pageNum 0 或者 1 --》 后台得到pageNum都为 0 ,被参数解析器自动转换为0
		// 页面传来 pageNum n --》 后台得到都为 0
		/**
		 * Configures whether to expose and assume 1-based page number indexes in the request parameters. Defaults to
		 * {@literal false}, meaning a page number of 0 in the request equals the first page. If this is set to
		 * {@literal true}, a page number of 1 in the request will be considered the first page.
		 * @param oneIndexedParameters the oneIndexedParameters to set
		 */
		resolver.setOneIndexedParameters(true);
		resolver.setFallbackPageable(PageRequest.of(0, 20));
		argumentResolvers.add(resolver);
	}

	/**
	 * 配置消息转换器
	 */
	@Override
	public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
		//清除掉原本的AbstractJackson2HttpMessageConverter。
		converters.removeIf((iter) -> {
			return iter instanceof AbstractJackson2HttpMessageConverter;
		});
		converters.add(0, new JsonConverer(MediaType.APPLICATION_JSON_UTF8));
	}

	/**
	 * 配置格式化器
	 */
	@Override
	public void addFormatters(FormatterRegistry registry) {
		//对字符串进行转义
		registry.addConverter(new Converter<String, String>() {

			private final Escaper escaper = HtmlEscapers.htmlEscaper();

			@Override
			public String convert(String source) {
				return escaper.escape(source);
			}
		});

	}

	/**
	 * 配置异步
	 */
	@Override
	public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
		configurer.setTaskExecutor(asyncConfig.getAsyncExecutor());
		configurer.setDefaultTimeout(asyncConfig.getProperties().getTimeout());
		configurer.registerCallableInterceptors(new TimeoutCallableProcessingInterceptor());
		configurer.registerDeferredResultInterceptors(new TimeoutDeferredResultProcessingInterceptor());
	}

	/**
	 * 配置默认媒体类型
	 */
	@Override
	public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
		configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
	}

}
